<template>
  <div class="video-container">
    <video :id="videoId" ref="videoElement" controls autoplay muted :height="height" :width="width" />
    <div v-if="playerReload" class="video-reload" @click.stop="reloadVideo">
      <el-icon><refresh-right /></el-icon>
      <div class="error-text">{{ playerErrorMsg }}</div>
    </div>
    <div v-else class="video-mini-reload" @click.stop="reloadVideo">
      <el-icon><refresh-right /></el-icon>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onActivated, onDeactivated, onUnmounted } from 'vue'
import flvjs from 'flv.js'

const props = defineProps({
  height: {
    type: [String, Number],
    default: 'auto'
  },
  width: {
    type: [String, Number],
    default: '100%'
  },
  id: {
    type: String,
    default: () => `flv-video-${Date.now()}${Math.random().toString().slice(2, 5)}`
  },
  flvPath: {
    type: String,
    required: true
  }
})

const videoElement = ref(null)
const playerReload = ref(false)
const playerErrorMsg = ref('')
const videoPlayer = ref(null)
const videoId = ref(props.id)

const showInOutVideo = (dom, url) => {
  if (videoPlayer.value) return

  const player = flvjs.createPlayer({
    type: 'flv',
    url
  })
  
  player.attachMediaElement(dom)
  player.load()
  player.play()
  videoPlayer.value = player

  player.on(flvjs.Events.ERROR, (errorType, errorDetail, errorInfo) => {
    console.error('flv error', errorType, errorDetail, errorInfo)
    const { code, msg } = errorDetail
    playerReload.value = true
    destroyVideo()

    if (code === 404) {
      playerErrorMsg.value = '视频资源未找到'
    } else if (msg) {
      playerErrorMsg.value = msg
    } else if (errorType === 'NetworkError') {
      playerErrorMsg.value = '网络有问题，请稍后重试'
    } else {
      playerErrorMsg.value = '视频出错，请稍后重试'
    }
  })
}

const showVideo = () => {
  if (flvjs.isSupported()) {
    const dom = videoElement.value
    if (props.flvPath && dom) {
      showInOutVideo(dom, props.flvPath)
    }
  } else {
    ElMessage.error('暂不支持视频播放')
  }
}

const reloadVideo = () => {
  playerReload.value = false
  playerErrorMsg.value = ''
  destroyVideo()
  showVideo()
}

const destroyVideo = () => {
  if (videoPlayer.value) {
    videoPlayer.value.pause()
    videoPlayer.value.unload()
    videoPlayer.value.detachMediaElement()
    videoPlayer.value.destroy()
    videoPlayer.value = null
  }
}

onMounted(() => {
  console.log('mounted')
  showVideo()
})

onActivated(() => {
  console.log('activated')
  const dom = videoElement.value
  if (props.flvPath && dom) {
    showInOutVideo(dom, props.flvPath)
  }
})

onDeactivated(() => {
  destroyVideo()
})

onUnmounted(() => {
  destroyVideo()
})
</script>

<style lang="scss" scoped>
.video-container {
  position: relative;
  
  .video-reload {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    color: #fff;
    text-align: center;
    font-size: 40px;

    .error-text {
      font-size: 14px;
      color: #f00;
    }
    
    &:hover {
      cursor: pointer;
    }
  }

  .video-mini-reload {
    position: absolute;
    right: 10px;
    top: 10px;
    color: #ccc;

    &:hover {
      cursor: pointer;
    }
  }
}
</style>